package com.fulihui.information.core.repository.impl;

import com.fulihui.information.biz.conv.DislikeConv;
import com.fulihui.information.common.ESortType;
import com.fulihui.information.core.repository.ContentRepository;
import com.fulihui.information.core.repository.DislikeRepository;
import com.fulihui.information.dal.dataobj.InfoDislike;
import com.fulihui.information.dal.dataobj.InfoDislikeExample;
import com.fulihui.information.dal.mapper.ExtInfoDislikeMapper;
import com.fulihui.information.dal.mapper.InfoDislikeMapper;
import com.fulihui.information.dto.ContentDTO;
import com.fulihui.information.dto.ContentListItemDTO;
import com.fulihui.information.dto.DislikeInfo;
import com.fulihui.information.dto.DislikeStat;
import com.fulihui.information.enums.EContentSortFields;
import com.fulihui.information.enums.EContentStatus;
import com.fulihui.information.enums.EDislikeSortFields;
import com.fulihui.information.enums.EDislikeStatus;
import com.fulihui.information.request.DislikeAddRequest;
import com.fulihui.information.request.DislikeQueryRequest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.near.servicesupport.error.Errors;
import org.near.servicesupport.error.InvokeServiceException;
import org.near.toolkit.common.DateUtils;
import org.near.toolkit.common.EnumUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import static org.near.toolkit.common.StringUtil.isBlank;
import static org.near.toolkit.common.StringUtil.isNotBlank;

/**
 *
 * Created by LeeSon on 2017/1/10 0010.
 */
@Repository
public class DislikeRepositoryImpl implements DislikeRepository {
    @Autowired
    private InfoDislikeMapper    dislikeMapper;
    @Autowired
    private ExtInfoDislikeMapper extDislikeMapper;
    @Autowired
    private ContentRepository    contentRepository;

    @Override
    public boolean isExist(String userId, String contentId) {
        InfoDislikeExample example = new InfoDislikeExample();
        example.createCriteria().andUserIdEqualTo(userId).andContentIdEqualTo(contentId);
        List<InfoDislike> infoDislikeList = dislikeMapper.selectByExample(example);
        return infoDislikeList.size() > 0;
    }

    @Override
    public boolean addDislike(DislikeAddRequest request) {
        InfoDislike record = new InfoDislike();
        BeanUtils.copyProperties(request, record);
        if (StringUtils.isNotBlank(record.getComment())) {
            try {
                record.setComment(Base64.encodeBase64String(record.getComment().getBytes("UTF-8")));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException();
            }
        }

        ContentListItemDTO listItemDTO = contentRepository.queryItemListById(record.getContentId());
        record.setTitle(listItemDTO.getTitle());

        record.setGmtCreate(new Date());
        record.setStatus(EDislikeStatus.UNCHECK.getCode());

        return dislikeMapper.insertSelective(record) > 0;
    }

    @Transactional
    @Override
    public boolean modifyStatus(Long dislikeId, String status, String operator) {
        InfoDislike infoDislike = dislikeMapper.selectByPrimaryKey(dislikeId);
        if (infoDislike.getStatus().equals(EDislikeStatus.UNCHECK.getCode())) {
            //只有未审核状态的记录才可以 更改状态
            InfoDislikeExample example = new InfoDislikeExample();
            InfoDislikeExample.Criteria criteria = example.createCriteria();
            criteria.andContentIdEqualTo(infoDislike.getContentId());
            criteria.andStatusEqualTo(EDislikeStatus.UNCHECK.getCode());
            InfoDislike record = new InfoDislike();
            record.setStatus(status);
            record.setOperator(operator);

            //批量审核
            int updateByExampleSelective = dislikeMapper.updateByExampleSelective(record, example);
            if (updateByExampleSelective > 0 && status.equals(EDislikeStatus.DELETE.getCode())) {
                //更改内容状态
                boolean modifyStatus = contentRepository.batchModifyStatus(
                    Collections.singleton(infoDislike.getContentId()),
                    EContentStatus.DELETE.getCode(), operator);
                if (!modifyStatus) {
                    throw new InvokeServiceException(Errors.Commons.SYSTEM_ERROR);
                }
            }
        }

        return true;
    }

    @Override
    public DislikeInfo detail(Long dislikeId, boolean haveContent) {
        DislikeInfo dislikeInfo = new DislikeInfo();

        InfoDislike infoDislike = dislikeMapper.selectByPrimaryKey(dislikeId);
        dislikeInfo.setDislike(DislikeConv.toDTO(infoDislike));

        if (haveContent) {
            ContentDTO contentDTO = contentRepository.detail(infoDislike.getContentId());
            dislikeInfo.setContent(contentDTO);
        }

        return dislikeInfo;
    }

    @Override
    public List<DislikeInfo> queryPage(DislikeQueryRequest request) {
        List<DislikeInfo> dislikeInfoList = new LinkedList<>();

        List<InfoDislike> dislikeList = extDislikeMapper.selectByExamplePage(
            buildInfoDislikeExample(request), request.start4Mysql(), request.getRows());

        if (!CollectionUtils.isEmpty(dislikeList)) {
            dislikeList.forEach(d -> {
                DislikeInfo dislikeInfo = new DislikeInfo();
                dislikeInfo.setDislike(DislikeConv.toDTO(d));

                ContentDTO contentDTO = contentRepository.detail(d.getContentId());
                dislikeInfo.setContent(contentDTO);

                dislikeInfoList.add(dislikeInfo);
            });
        }

        return dislikeInfoList;
    }

    @Override
    public int queryPageCount(DislikeQueryRequest request) {
        return extDislikeMapper.selectByExamplePageCount(buildInfoDislikeExample(request));
    }

    private InfoDislikeExample buildInfoDislikeExample(DislikeQueryRequest request) {
        try {
            InfoDislikeExample example = new InfoDislikeExample();
            InfoDislikeExample.Criteria criteria = example.createCriteria();

            if (isNotBlank(request.getTimeStart())) {
                criteria.andGmtCreateGreaterThanOrEqualTo(
                    DateUtils.parseWebFormat(request.getTimeStart()));
            }

            if (isNotBlank(request.getTimeEnd())) {
                Date date = DateUtils.parseWebFormat(request.getTimeEnd());
                date.setHours(23);
                date.setMinutes(59);
                date.setSeconds(59);
                criteria.andGmtCreateLessThanOrEqualTo(date);
            }

            if (isNotBlank(request.getStatus())) {
                criteria.andStatusEqualTo(request.getStatus());
            }

            if (isNotBlank(request.getType())) {
                criteria.andTypeEqualTo(request.getType());
            }

            if (isNotBlank(request.getTitle())) {
                criteria.andTitleLike("%" + request.getTitle() + "%");
            }

            if (isNotBlank(request.getSortFiled())) {
                String sortField = EnumUtil
                    .queryByCode(request.getSortFiled(), EDislikeSortFields.class).getDesc();
                example.setOrderByClause(sortField + (isBlank(request.getSortType()) ? ""
                    : (" " + request.getSortType())));
            } else {
                example.setOrderByClause(
                    EContentSortFields.GMT_CREATE.getDesc() + " " + ESortType.DESC.getCode());
            }

            return example;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public DislikeStat stat() {
        DislikeStat stat = new DislikeStat();

        InfoDislikeExample example1 = new InfoDislikeExample();
        List<InfoDislike> infoDislikeList = dislikeMapper.selectByExample(example1);
        stat.setAll(infoDislikeList.size());

        InfoDislikeExample example2 = new InfoDislikeExample();
        InfoDislikeExample.Criteria criteria = example2.createCriteria();
        Date date1 = new Date();
        date1.setHours(0);
        date1.setMinutes(0);
        date1.setSeconds(0);
        criteria.andGmtCreateGreaterThanOrEqualTo(date1);
        Date date2 = new Date();
        date2.setHours(23);
        date2.setMinutes(59);
        date2.setSeconds(59);
        criteria.andGmtCreateLessThanOrEqualTo(date2);
        infoDislikeList = dislikeMapper.selectByExample(example2);
        stat.setIncr(infoDislikeList.size());

        InfoDislikeExample example3 = new InfoDislikeExample();
        example3.createCriteria().andStatusEqualTo(EDislikeStatus.UNCHECK.getCode());
        infoDislikeList = dislikeMapper.selectByExample(example3);
        stat.setWait(infoDislikeList.size());

        return stat;
    }
}